package com.px.project.module.ml.controller;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import com.px.common.dto.BaseBodyDto;
import com.px.common.dto.BaseQueryDto;
import com.px.common.dto.ProcessExecuteDto;
import com.px.common.vo.DataImportResultVo;
import com.px.project.module.ml.dto.storage.StorageDto;
import com.px.project.module.ml.dto.storage.StorageQueryDto;
import com.px.project.module.ml.entity.Storage;
import com.px.project.module.ml.service.IStorageService;
import com.px.project.module.ml.vo.storage.StorageExportVo;
import com.px.project.module.ml.vo.storage.StorageVo;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import lombok.RequiredArgsConstructor;

/**
 * 物资系统》入库单 前端控制器
 *
 * @author 品讯科技
 * @since 2023-11-14
 */
@RestController
@RequestMapping("/ml/storage")
@RequiredArgsConstructor
public class StorageController {

    private final IStorageService storageService;

    /**
     * 根据id查询入库单详情
     *
     * @param id id
     * @return {@link StorageVo }
     * @author 品讯科技
     * @date 2024-08
     */
    @GetMapping("/getById/{id}")
    public StorageVo getById(@PathVariable("id") Long id) {
        return storageService.getById(id);
    }

    /**
     * 分页查询入库单
     * searchKey支持模糊匹配单号,入库名称
     *
     * @param pageDto  分页 DTO
     * @param queryDto 查询 DTO
     * @return {@link Page }<{@link StorageVo }>
     * @author 品讯科技
     * @date 2024-08
     */
    @GetMapping("/page")
    public Page<StorageVo> page(@Validated BaseQueryDto<StorageVo> pageDto, StorageQueryDto queryDto) {
        return storageService.page(pageDto, queryDto);
    }

    /**
     * 检查批号是否重复
     *
     * @param storage 存储
     * @return {@link Boolean }
     * @author 品讯科技
     * @date 2024-08
     */
    @GetMapping("/checkBatchNum")
    public Boolean checkBatchNum(Storage storage) {
        return storageService.checkBatchNum(storage);
    }

    /**
     * 保存入库单(草稿)
     *
     * @param dto DTO
     * @return {@link Long }
     * @author 品讯科技
     * @date 2024-08
     */
    @PostMapping("/save")
    public Boolean save(@RequestBody StorageDto dto) {
        return storageService.save(dto, Boolean.TRUE);
    }

    /**
     * 更新入库单(草稿),不允许更新工单号以及流程有关字段
     *
     * @param dto DTO
     * @return {@link Boolean }
     * @author 品讯科技
     * @date 2024-08
     */
    @PostMapping("/updateById")
    public Boolean updateById(@RequestBody StorageDto dto) {
        return storageService.updateById(dto, Boolean.TRUE);
    }

    /**
     * 删除入库单
     * 只能删除草稿(待发起)
     *
     * @param dto 请求body基础 DTO
     * @return {@link Boolean }
     * @author 品讯科技
     * @date 2024-08
     */
    @PostMapping("/removeByIds")
    public Boolean removeByIds(@RequestBody @Validated BaseBodyDto dto) {
        return storageService.removeByIds(dto.getIdList());
    }

    /**
     * 启动流程
     * 支持先保存为草稿，再启动(带上业务id)，或者直接启动(没有业务id)
     *
     * @param executeDto 执行 DTO
     * @return {@link Boolean }
     * @author 品讯科技
     * @date 2024-08
     */
    @PostMapping("/startProcess")
    public Boolean startProcess(@RequestBody @Validated ProcessExecuteDto<StorageDto> executeDto) {
        return storageService.startProcess(executeDto);
    }

    /**
     * 执行流程
     *
     * @param executeDto 执行 DTO
     * @return {@link Boolean }
     * @author 品讯科技
     * @date 2024-08
     */
    @PostMapping("/executeTask")
    public Boolean executeTask(@RequestBody @Validated ProcessExecuteDto<StorageDto> executeDto) {
        return storageService.executeTask(executeDto);
    }

    /**
     * 终止流程(不通过)
     *
     * @param id 编号
     * @return {@link Boolean }
     * @author 品讯科技
     * @date 2024-08
     */
    @GetMapping("/terminate/{id}")
    public Boolean terminate(@PathVariable("id") Long id) {
        return storageService.terminate(id);
    }

    /**
     * 导入 Excel,导入入库单主表信息
     *
     * @param file 文件
     * @return {@link DataImportResultVo }
     * @throws IOException ioexception
     * @author 品讯科技
     * @date 2024-08
     */
    @PostMapping("/importExcel")
    public DataImportResultVo importExcel(@RequestParam("file") MultipartFile file) throws IOException {
        return storageService.importExcel(file);
    }

    /**
     * 导出excel
     *
     * @param searchKey 搜索键
     * @param queryDto  查询 dto
     * @param response  响应
     * @throws IOException ioexception
     * @author 品讯科技
     * @date 2024-08
     */
    @GetMapping(value = "/exportExcel")
    public void export(String searchKey,StorageQueryDto queryDto,HttpServletResponse response) throws IOException {
        List<StorageExportVo> list = storageService.exportExcel(searchKey,queryDto);

        response.setCharacterEncoding(String.valueOf(StandardCharsets.UTF_8));
        // 允许除默认的首部可以作为响应的一部分暴露给外部
        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
        // 通过响应头告诉浏览器该文件为下载文件，并指定默认文件名
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("入库单信息", StandardCharsets.UTF_8) + ".xlsx");
        response.setContentType("application/octet-stream");

        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        //内容策略
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        //设置居中
        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

        HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);

        EasyExcel.write(response.getOutputStream(), StorageExportVo.class).registerWriteHandler(horizontalCellStyleStrategy)
                .sheet("入库单信息").doWrite(list);
    }

}
